package com.chinacoal.microservice.impl.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.plugins.Page;
import com.chinacoal.microservice.api.CcmsDomainsClient;
import com.chinacoal.microservice.api.OrgOpenClient;
import com.chinacoal.microservice.exception.MessageException;
import com.chinacoal.microservice.impl.mapper.ApprovalHistoryMapper;
import com.chinacoal.microservice.impl.mapper.InstanceMapper;
import com.chinacoal.microservice.impl.mapper.WorkItemMapper;
import com.chinacoal.microservice.impl.service.ApprovalHistoryService;
import com.chinacoal.microservice.impl.service.TaskPushService;
import com.chinacoal.microservice.impl.service.WorkFlowService;
import com.chinacoal.microservice.impl.util.ProcessFun;
import com.chinacoal.microservice.model.organization.vo.EmployeeVO;
import com.chinacoal.microservice.model.rbac.CcmsDomains;
import com.chinacoal.microservice.model.wofkflow.ApproveParam;
import com.chinacoal.microservice.model.wofkflow.QueryTaskListParam;
import com.chinacoal.microservice.model.wofkflow.entity.ApprovalHistoryEntity;
import com.chinacoal.microservice.model.wofkflow.entity.InstanceEntity;
import com.chinacoal.microservice.model.wofkflow.entity.WorkItemEntity;
import com.chinacoal.microservice.model.wofkflow.resource.WrapAttribute;
import com.chinacoal.microservice.util.PrimaryKey;
import com.chinacoal.microservice.util.result.Result;
import com.chinacoal.microservice.util.tool.Tool;
import com.eos.system.utility.StringUtil;
import com.eos.workflow.api.BPSServiceClientFactory;
import com.eos.workflow.api.IBPSServiceClient;
import com.eos.workflow.data.WFActivityDefine;
import com.eos.workflow.omservice.WFParticipant;

/**
 * @Package: com.chinacoal.microservice.impl.service.impl.WorkFlowServiceImpl
 * @ClassName: WorkFlowServiceImpl
 * @ClassDesc: 工作流管理ServiceImpl
 * @Createby: sunh
 * @CreatedDate: 2019-11-29 10:18:11
 */
@Service
public class WorkFlowServiceImpl implements WorkFlowService {

    @Resource
    private ApprovalHistoryMapper workFlowMapper;
    @Resource
    private InstanceMapper instanceMapper;
    @Resource
    private WorkItemMapper workItemMapper;
    @Resource
    private ApprovalHistoryService approvalHistoryService;
    @Resource
    private OrgOpenClient orgOpenClient;
    @Resource
    private CcmsDomainsClient domainClient;
    @Resource
    private TaskPushService taskPushService;

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public IBPSServiceClient getIBPSServiceClient(Integer userId, String name) throws Exception {

        String empId = getEmpByUserId(userId).toString();

        // 获取工作流服务
        BPSServiceClientFactory.getLoginManager().setCurrentUser(empId, name);
        IBPSServiceClient client = BPSServiceClientFactory.getDefaultClient();

        return client;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public boolean setBusinessDate(IBPSServiceClient client, Long instanceId, Map<String, Object> businessParam) throws Exception {

        if (client == null) {

            throw new MessageException("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (businessParam != null && businessParam.size() > 0 && instanceId != null) {
            // 提交业务数据
            client.getRelativeDataManager().setRelativeDataBatch(instanceId, businessParam);
        }

        return true;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public String getBusinessDate(IBPSServiceClient client, Long instanceId, String name) throws Exception {

        String result = null;
        if (client == null) {

            throw new MessageException("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (instanceId != null) {
            // 获取业务数据
            result = Tool.nvl(client.getRelativeDataManager().getRelativeData(instanceId, name), null);
        }
        return result;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity createProcessInstance(IBPSServiceClient client, String processCode) throws Exception {

        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(processCode)) {
            throw new Exception("检测到无法识别的流程名称，请检查调用参数！");
        }

        // 创建流程实例
        String instanceName = PrimaryKey.newKey();
        Long instanceId = client.getProcessInstManager().createProcessInstance(processCode, instanceName, instanceName);

        // 获取实例数据
        InstanceEntity instanceEntity = instanceMapper.selectById(instanceId);

        return instanceEntity;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity processSubmit(IBPSServiceClient client, Long instanceId, Map<String, Object> businessParam) throws Exception {

        // 1、校验
        if (client == null) {
            throw new MessageException("获取工作流服务失败，请稍后再试或联系管理员！");
        }

        // 创建流程实例并提交流程
        // instanceId = client.getProcessInstManager().createAndStartProcessInstance(processCode, instanceName, instanceName);

        // 2、获取实例数据
        InstanceEntity instanceEntity = instanceMapper.selectById(instanceId);

        // 3、保存业务数据
        setBusinessDate(client, instanceId, businessParam);

        // 4、启动流程
        String currentState = instanceEntity.getCurrentState();
        if ("1".equals(currentState)) {
            // 实例未启动 -- 提交流程
            client.getProcessInstManager().startProcessInstance(instanceId);
        } else if ("2".equals(currentState)) {
            // 实例已启动 -- 重启流程
            return instanceEntity;
        } else {
            throw new MessageException("检测流程已经终止或挂起，无法再次提交！");
        }

        // 5、设置标题
        setTaskTitle(client, instanceId);

        return instanceEntity;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public boolean completeFill(IBPSServiceClient client, Long instanceId) throws Exception {

        try {
            // 获取最新的待办
            List<WorkItemEntity> workItemList = workItemMapper.getWorkItemByInstanceId(instanceId);

            if (workItemList == null) {
                throw new Exception("未找到处于活动的待办");
            } else if (workItemList.size() > 1) {
                throw new Exception("最新的待办不是填报节点的待办");
            } else {
                WorkItemEntity workItemEntity = workItemList.get(0);
                Long processId = workItemEntity.getProcessId();
                String ActivityId = workItemEntity.getActivityId().toString();
                System.out.println(1);
                // 根据流程id获取到开始节点后的第一个节点（填报节点）
                WFActivityDefine editActivity = client.getDefinitionQueryManager().queryNextActivities(processId, "startActivity").get(0);
                String editActivityId = editActivity.getId();

                if (!ActivityId.equals(editActivityId)) {
                    throw new Exception("最新的待办不是填报节点的待办");
                }
                System.out.println(2);
                // 执行同意
                ApproveParam approveParam = new ApproveParam();
                approveParam.setOpcode("1000");
                approveParam.setApprovalOpinion("完成");
                approveParam.setTaskId(workItemEntity.getTaskId());
                approveAgreed(client, approveParam);

                // 获取最新的待办
                workItemList = workItemMapper.getWorkItemByInstanceId(instanceId);
                System.out.println(3);
                // 推送待办
                taskPushService.taskPushAdd(workItemList);
                System.out.println(4);
            }
        } catch (Exception e) {
            System.out.println("填报节点执行审批通过时失败，原因");
            e.printStackTrace();
//            throw new Exception("填报节点执行审批通过时失败，原因：" + ProcessFun.getExceptionMessage(e));
        }

        return true;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveAgreed(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，同意失败");

        // 生成历史记录
        addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

        // 完成待办
        client.getWorkItemManager().finishWorkItem(taskId, false);

        // 设置标题
        Long instanceId = workItemEntity.getInstanceId();
        setTaskTitle(client, instanceId);

        return instanceMapper.selectById(instanceId);
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveRejected(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，驳回失败");

        // 生成历史记录
        addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

        // 根据流程id获取到开始节点后的第一个节点
        Long processId = workItemEntity.getProcessId();
        WFActivityDefine editActivity = client.getDefinitionQueryManager().queryNextActivities(processId, "startActivity").get(0);

        // 待办回退至该节点
        String editActivityId = editActivity.getId();
        Long activityId = workItemEntity.getActivityInsId();
        client.getBackActivityManager().backActivity(activityId, editActivityId, "simple");

        // 设置标题
        Long instanceId = workItemEntity.getInstanceId();
        setTaskTitle(client, instanceId);

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveRecall(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        Long instanceId = approveParam.getInstanceId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (instanceId == null) {
            throw new Exception("检测到无法识别的实例Id，请检查调用参数！");
        }
        // ====================================校验结束===============================================

        List<WorkItemEntity> workItemList = workItemMapper.getWorkItemByInstanceId(instanceId);

        if (workItemList == null || workItemList.size() < 1) {
            throw new Exception("流程启动成功，但没有生成待办");
        }

        WorkItemEntity workItemEntity = workItemList.get(0);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，撤回失败");

        // 生成历史记录
        addApprovalHistory(client, workItemEntity, null, approveParam.getOpcode());

        // 根据流程id获取到开始节点后的第一个节点
        Long processId = workItemEntity.getProcessId();
        WFActivityDefine editActivity = client.getDefinitionQueryManager().queryNextActivities(processId, "startActivity").get(0);

        // 待办回退至该节点
        String editActivityId = editActivity.getId();
        Long activityId = workItemEntity.getActivityInsId();
        client.getBackActivityManager().backActivity(activityId, editActivityId, "simple");

        // 设置标题
        setTaskTitle(client, instanceId);

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveFallback(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        String isEditNode = approveParam.getIsEditNode();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，回退失败");

        InstanceEntity InstanceEntity = new InstanceEntity();
        List<WrapAttribute> optionList = approveParam.getOptions();
        if (optionList == null || optionList.size() < 1) {

            // 返回可回退节点
            Long activityInsId = workItemEntity.getActivityInsId();
            List<WFActivityDefine> wfadlist = client.getBackActivityManager().getPreviousActivities(activityInsId, "startActivity");

            // 去掉填报节点
            String editActivityId = null;
            if ("Y".equals(isEditNode)) {
                Long processId = workItemEntity.getProcessId();
                WFActivityDefine nextActivity = client.getDefinitionQueryManager().queryNextActivities(processId, "startActivity").get(0);
                editActivityId = nextActivity.getId();
            }

            List<WrapAttribute> activityList = ProcessFun.getOptionListWAD(wfadlist, true, editActivityId);
            InstanceEntity = instanceMapper.selectById(workItemEntity.getInstanceId());
            InstanceEntity.setResultParam(activityList);
        } else if (optionList.size() > 1) {
            throw new Exception("回退的节点有且只能存在一个！");
        } else {

            // 生成历史记录
            addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

            // 执行回退
            long startActivityInstId = workItemEntity.getActivityInsId();        // 当前节点id
            String endActivityId = optionList.get(0).getId();                    // 回退节点id
            client.getBackActivityManager().backActivity(startActivityInstId, endActivityId, "simple"); // 执行回退

            InstanceEntity = instanceMapper.selectById(workItemEntity.getInstanceId());
            InstanceEntity.setResultParam(new ArrayList<WrapAttribute>());

            // 设置标题
            Long instanceId = workItemEntity.getInstanceId();
            setTaskTitle(client, instanceId);
        }

        return InstanceEntity;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveConsult(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，征询失败");

        List<WrapAttribute> optionList = approveParam.getOptions();

        if (optionList == null || optionList.size() < 1) {

            throw new Exception("被征询意见的人员不能少于一个");
        } else {

            // 生成历史记录
            addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

            // 组装人员列表
            WFParticipant[] WFParticipants = new WFParticipant[optionList.size()];

            int i = 0;
            for (WrapAttribute option : optionList) {
                WFParticipants[i] = new WFParticipant(option.getId(), option.getName(), option.getType());
                i++;
            }

            // 执行征询（协办）
            client.getDelegateManager().delegateWorkItem(taskId, WFParticipants, "HELP");
        }

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveDelegate(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，委派失败");

        List<WrapAttribute> attrList = approveParam.getOptions();

        if (attrList == null || attrList.size() != 1) {
            throw new Exception("被委派审批的人员有且只能有一个");
        } else {
            // 获取被委派人
            String empId = attrList.get(0).getId();
            String empName = attrList.get(0).getName();

            // 生成历史记录
            addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

            // 执行委派(改派)
            WFParticipant[] participantArr = {new WFParticipant(empId, empName, "emp")};
            client.getWorkItemManager().reassignWorkItemEx(taskId, participantArr);
        }

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveTranspond(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，委派失败");

        List<WrapAttribute> optionList = approveParam.getOptions();

        if (optionList == null || optionList.size() < 1) {
            throw new Exception("被征询意见的人员不能少于一个");
        } else {

            // 生成历史记录
            addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

            // 组装人员列表
            WFParticipant[] WFParticipants = new WFParticipant[optionList.size()];

            int i = 0;
            for (WrapAttribute option : optionList) {
                WFParticipants[i] = new WFParticipant(option.getId(), option.getName(), option.getType());
                i++;
            }

            // 执行转发（代办）
            client.getDelegateManager().delegateWorkItem(taskId, WFParticipants, "DELEG");
        }

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveRepeal(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，撤销审批失败");

        boolean isRecall = client.getWorkItemDrawbackManager().isDrawbackEnable(taskId);
        if (isRecall) {

            // 生成历史记录
            addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

            // 执行撤销
            client.getWorkItemDrawbackManager().drawbackWorkItem(taskId, true, false);

            // 设置标题
            Long instanceId = workItemEntity.getInstanceId();
            setTaskTitle(client, instanceId);
        }

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveTerminate(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，终止流程失败");

        // 生成历史记录
        addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

        // 终止流程
        Long activityInsId = workItemEntity.getActivityInsId();
        client.getProcessInstManager().terminateProcessInstance(activityInsId);

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveRestart(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，重启流程失败");

        // 生成历史记录
        addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

        // 重启流程
        Long activityInsId = workItemEntity.getActivityInsId();
        client.getProcessInstManager().restartFinishedProcessInst(activityInsId);

        // 设置标题
        Long instanceId = workItemEntity.getInstanceId();
        setTaskTitle(client, instanceId);

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveHangUp(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (StringUtil.isEmpty(approvalOpinion)) {
            throw new Exception("检测到无法识别的审批意见，请检查调用参数！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，流程挂起失败");

        // 生成历史记录
        addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

        // 挂起流程
        Long activityInsId = workItemEntity.getActivityInsId();
        client.getProcessInstManager().suspendProcessInstance(activityInsId);

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public InstanceEntity approveRestore(IBPSServiceClient client, ApproveParam approveParam) throws Exception {

        String approvalOpinion = approveParam.getApprovalOpinion();
        Long taskId = approveParam.getTaskId();

        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (taskId == null) {
            throw new MessageException("待办id不能为空: taskId");
        }
        // ====================================校验结束===============================================

        // 获取当前待办
        WorkItemEntity workItemEntity = workItemMapper.selectById(taskId);

        if (workItemEntity == null) throw new Exception("未找到当前的待办信息，流程恢复失败");

        // 生成历史记录
        addApprovalHistory(client, workItemEntity, approvalOpinion, approveParam.getOpcode());

        // 恢复流程
        Long activityInsId = workItemEntity.getActivityInsId();
        client.getProcessInstManager().resumeProcessInstance(activityInsId);

        return instanceMapper.selectById(workItemEntity.getInstanceId());
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public void deleteInstanceById(IBPSServiceClient client, List<Long> instanceIds) throws Exception {
        // ====================================校验开始===============================================
        // 参数校验
        if (client == null) {
            throw new Exception("获取工作流服务失败，请稍后再试或联系管理员！");
        } else if (instanceIds == null || instanceIds.size() < 1) {
            return;
        }
        // ====================================校验结束===============================================

        long[] insIds = new long[instanceIds.size()];
        int i = 0;
        for (Long InstanceId : instanceIds) {
            if (instanceIds.get(i) != null) {
                insIds[i++] = InstanceId;
            }
        }
        client.getProcessInstManager().deleteProcessInstBatch(insIds);
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public Page<WorkItemEntity> getTaskList(Integer page, Integer pageSize, QueryTaskListParam queryParam) throws
            Exception {

        // 获取系统id
        String sysCode = queryParam.getSysCode();
        if (StringUtils.isEmpty(sysCode)) {
            queryParam.setDomainId(null);
        } else {
            CcmsDomains domainEntity = domainClient.findDomainByIamClientId(sysCode).getData();
            if (domainEntity == null) {
                throw new MessageException("请求中未提交系统码或提交的系统码【" + sysCode + "】无效，请确认！");
            }
            String domainId = domainEntity.getDomainId();
            queryParam.setDomainId(domainId);
        }

        // 参数包装
        Integer empId = getEmpByUserId(queryParam.getUserId());
        queryParam.setEmpId(empId);
        queryParam.setTaskType(10);

        // 设置分页
        Page<WorkItemEntity> pages = ProcessFun.getPage(page, pageSize);

        // 获取待办数据
        List<WorkItemEntity> workItemList = workItemMapper.getWorkItemList(pages, queryParam);

        pages.setRecords(workItemList);

        return pages;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    public Page<WorkItemEntity> getAchTaskList(Integer page, Integer pageSize, QueryTaskListParam queryParam) throws
            Exception {

        // 获取系统id
        String sysCode = queryParam.getSysCode();
        if (StringUtils.isEmpty(sysCode)) {
            queryParam.setDomainId(null);
        } else {
            CcmsDomains domainEntity = domainClient.findDomainByIamClientId(sysCode).getData();
            if (domainEntity == null) {
                throw new MessageException("请求中未提交系统码或提交的系统码【" + sysCode + "】无效，请确认！");
            }
            String domainId = domainEntity.getDomainId();
            queryParam.setDomainId(domainId);
        }

        Integer empId = getEmpByUserId(queryParam.getUserId());
        queryParam.setEmpId(empId);
        queryParam.setTaskType(12);

        // 设置分页
        Page<WorkItemEntity> pages = ProcessFun.getPage(page, pageSize);

        // 获取已办数据
        List<WorkItemEntity> workItemList = workItemMapper.getWorkItemList(pages, queryParam);

        pages.setRecords(workItemList);

        return pages;
    }

    /**
     * @param client
     * @param workItemEntity
     * @param approvalOpinion
     * @param opcode          }
     * @Package: com.chinacoal.microservice.impl.service.impl.WorkFlowServiceImpl.addApprovalHistory
     * @MethodName: addApprovalHistory
     * @MethodDesc: 组装审批历史并新增
     * @ParamList: {
     * @Return: void
     * @Createby: sunh
     * @CreatedDate: 2019-12-03 11:05:01
     */
    private void addApprovalHistory(IBPSServiceClient client, WorkItemEntity workItemEntity, String
            approvalOpinion, String opcode) throws Exception {

        Long taskId = workItemEntity.getTaskId();
        Long processId = workItemEntity.getProcessId();
        Long instanceId = workItemEntity.getInstanceId();
        String taskTitle = workItemEntity.getTaskTitle();
        Long submitUser = workItemEntity.getSubmitUser();
        Long activityInsId = workItemEntity.getActivityInsId();
        String activityId = workItemEntity.getActivityId();
        String activityName = workItemEntity.getActivityName();
        Long activityUser = workItemEntity.getActivityUser();
        Date startDate = workItemEntity.getStartDate();
        Date endDate = new Date();
        String taskDesc = workItemEntity.getTaskDesc();
        String opcodeName = ProcessFun.getOpcodeName(opcode);

        ApprovalHistoryEntity approvalHisEntity = new ApprovalHistoryEntity();
        approvalHisEntity.setTaskHisId(PrimaryKey.newKey());
        approvalHisEntity.setTaskId(taskId);
        approvalHisEntity.setProcessId(processId);
        approvalHisEntity.setInstanceId(instanceId);
        approvalHisEntity.setTaskTitle(taskTitle);
        approvalHisEntity.setSubmitUser(submitUser);
        approvalHisEntity.setActivityInsId(activityInsId);
        approvalHisEntity.setActivityId(activityId);
        approvalHisEntity.setActivityName(activityName);
        approvalHisEntity.setActivityUser(activityUser);
        approvalHisEntity.setStartDate(startDate);
        approvalHisEntity.setEndDate(endDate);
        approvalHisEntity.setTaskDesc(taskDesc);
        approvalHisEntity.setApprovalOpinion(approvalOpinion);
        approvalHisEntity.setOpcode(opcode);
        approvalHisEntity.setEndDate(endDate);
        approvalHisEntity.setOpcodeName(opcodeName);

        approvalHistoryService.insert(approvalHisEntity);
    }

    /**
     * @param userId }
     * @Package: com.chinacoal.microservice.impl.service.impl.WorkFlowServiceImpl.getEmpByUserId
     * @MethodName: getEmpByUserId
     * @MethodDesc: 获取员工Id
     * @ParamList: {
     * @Return: Integer
     * @Createby: sunh
     * @CreatedDate: 2019-12-03 15:20:09
     */
    private Integer getEmpByUserId(Integer userId) throws Exception {

        Result<EmployeeVO> empResult = orgOpenClient.getEmpDetial(userId, null);
        if (empResult == null || empResult.getData() == null || empResult.getData().getEmpId() == null) {
            throw new MessageException("当前用户没有对应的员工");
        }

        Integer empId = empResult.getData().getEmpId();

        return Tool.toInteger(empId.toString());
    }

    /**
     * @param instanceId }
     * @Package: com.chinacoal.microservice.impl.service.impl.WorkFlowServiceImpl.setTaskTitle
     * @MethodName: setTaskTitle
     * @MethodDesc: 设置待办标题
     * @ParamList: {
     * @Return: void
     * @Createby: sunh
     * @CreatedDate: 2019-12-18 18:36:57
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})
    private void setTaskTitle(IBPSServiceClient client, Long instanceId) throws Exception {
        try {
            String taskTitle = null;

            taskTitle = getBusinessDate(client, instanceId, "taskTitle");

            if (StringUtils.isEmpty(taskTitle)) {
                // 获取最新的待办
                List<WorkItemEntity> workItemList = workItemMapper.getWorkItemByInstanceId(instanceId);

                if (workItemList == null || workItemList.size() < 1) return;

                WorkItemEntity workItemEntity = workItemList.get(0);
                String submitUserName = workItemEntity.getSubmitUserName();
                Long processId = workItemEntity.getProcessId();
                String activityId = workItemEntity.getActivityId();

                // 获取当前节点属性（扩展属性，例如：待办标题等）
                String xml = client.getDefinitionQueryManager().getExtendAttribute(processId, activityId);
                // 解析xml分解出扩展属性列表
                List<Map<String, String>> attrList = ProcessFun.parseAttrXML(xml);
                // 获取标题项
                for (Map<String, String> map : attrList) {
                    if ("title".equals(map.get("key"))) {
                        taskTitle = map.get("value").replace("$userId", submitUserName);
                    }
                }

                if (StringUtils.isEmpty(taskTitle)) {
                    taskTitle = "请审批" + submitUserName + "提交的流程";
                }
            }

            String businessId = getBusinessDate(client, instanceId, "businessId");
            String bizCode = getBusinessDate(client, instanceId, "bizCode");
            String sysCode = getBusinessDate(client, instanceId, "sysCode");

            Map<String, Object> param = new HashMap<String, Object>();
            param.put("instanceId", instanceId);
            param.put("taskTitle", taskTitle);
            param.put("currentstate", "10");
            param.put("businessId", businessId);
            param.put("bizCode", bizCode);
            param.put("sysCode", sysCode);
            workItemMapper.settingTitle(param);
        } catch (Exception e) {

        }
    }
}
